package cn.mjnxin.iot.connector.handle;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.List;

import cn.mjnxin.iot.base.domain.ChannelData;
import cn.mjnxin.iot.base.log.LogWorker;
import cn.mjnxin.iot.base.util.CommonUtil;
import cn.mjnxin.iot.connector.cache.HostRuntimeCache;
import cn.mjnxin.iot.connector.context.IConnectorContext;
import cn.mjnxin.iot.connector.worker.Gate2ConnectorWorker;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;

/**
 * 接收前置报文转发终端
 * @author CLG
 * @date 2021年10月9日 
 * @version V1.0.0
 */
@Sharable
public class ConnectorAsClient2GateInHandler extends ChannelInboundHandlerAdapter{
    private final Gate2ConnectorWorker instance = Gate2ConnectorWorker.getInstance();
	private final IConnectorContext context;
	public ConnectorAsClient2GateInHandler(IConnectorContext context) {
		this.context = context;
	}
	
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		if(msg instanceof List){
            @SuppressWarnings("unchecked")
            List<ChannelData> dataList = (List<ChannelData>) msg;
            for (ChannelData channelData : dataList) {
            	instance.add(channelData);
            }
        }else{
            ChannelData channelData = (ChannelData)msg;
            instance.add(channelData);
        }
    }
    
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
//        super.channelActive(ctx);
        /**
         * 缓存会话
         */
        Channel channel = ctx.channel();
        InetSocketAddress insocket = (InetSocketAddress)channel.remoteAddress();
        String gateAddress = CommonUtil.getIpAddress(insocket);
        HostRuntimeCache.addGateChannel(gateAddress, channel);
    }
	
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("ConnectorAsClient2Gate.channelInactive(ChannelHandlerContext ctx)");
        super.channelInactive(ctx);

        Channel channel = ctx.channel();
        InetSocketAddress insocket = (InetSocketAddress)channel.remoteAddress();
        String gateAddress = CommonUtil.getIpAddress(insocket);
        HostRuntimeCache.removeGateChannel(gateAddress);
        context.clearPeerData();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("ConnectorAsClient2Gate.exceptionCaught(ChannelHandlerContext ctx, Throwable cause)");
        Channel channel = ctx.channel();
        InetSocketAddress insocket = (InetSocketAddress)channel.remoteAddress();
        if (cause instanceof IOException || cause instanceof OutOfMemoryError) {
            LogWorker.logForce(String.format("网关: %s 断连", insocket.toString()));
        } else {
            LogWorker.logForce(String.format("网关: %s 其他异常", insocket.toString()));
        }
        super.exceptionCaught(ctx, cause);
    }
    
    /**
     * 心跳检测触发的事件通过本方法捕获
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        System.out.println("ConnectorAsClient2Gate.userEventTriggered(ChannelHandlerContext ctx, Object evt)" + evt);
        if (evt instanceof IdleStateEvent) {
            IdleState state = ((IdleStateEvent) evt).state();
            if(state == IdleState.ALL_IDLE ){
                LogWorker.logForce(String.format("空闲检测：没有收发包"));
				ChannelFuture fcutrue = ctx.close();
				fcutrue.addListener(new ChannelFutureListener() {
					public void operationComplete(ChannelFuture future) throws Exception {
						Channel channel = future.channel();
						InetSocketAddress insocket = (InetSocketAddress) channel.remoteAddress();
                        if (insocket != null) {
							String ipAddress = CommonUtil.getIpAddress(insocket);
							LogWorker.logForce(String.format("网关 %s 没发包超时下线成功", ipAddress));
                        }
						channel.close();
					}
				});
            }
        }else{  
            super.userEventTriggered(ctx, evt);
        }
    }
}
